/**
 *  mmodlist.c -  crea una entrada /proc/mmodlist y permite la gestion de
 *  varias listas de enteros
 *  http://www.cs.bham.ac.uk/~exr/teaching/lectures/systems/08_09/docs/kernelAPI/x1820.html
 *  http://www.roman10.net/linux-kernel-programmingmemory-allocation/
 *  http://www.makelinux.net/ldd3/chp-11-sect-5
 *  http://stackoverflow.com/questions/15332381/linux-list-h-how-to-safely-remove-items-from-the-list
 *  http://stackoverflow.com/questions/14174650/how-to-delete-a-linked-list-in-c
 */

#include <linux/module.h>	/* Specifically, a module */
#include <linux/kernel.h>	/* We're doing kernel work */
#include <linux/proc_fs.h>	/* Necessary because we use the proc fs */
#include <asm/uaccess.h>	/* for copy_from_user */
#include <linux/vmalloc.h>  /* memoria */
#include <linux/list.h>		/* para listas */

#define PROCFS_MAX_SIZE		512
#define MAX_WORDS 10
#define PROC_ROOT_NAME 		"mmmodlist"
#define PROC_ACT_NAME		"activar"
#define PROC_DES_NAME		"desactivar"
#define MONITOR				"monitor"

/** Necesitamos:
 * 1. Un contador para saber cuantos módulos de lista tenemos cargados
 * 2. 3 entradas (activar, desactivar y monitor), (Escr,Escr,Lect)
 * 3. Entrada activar -> recibira el nombre de una lista y cargara el modulo si no esta ya cargados
 * 4. Entrada desactivar -> recibira el nombre de una lista y desacargara el modulo de una lista si esta cargados
 * 5. Entrada monitor -> mostrara el nombre de las listas que existen actualmente
 */
 
MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("Practica 2b AISO");

MODULE_AUTHOR("Raul Vicente Bueno Sevilla - Jesus Francisco Lopez San Jose");

/****************************** GESTION DEL MANAGER ******************************/
static int numListas = 0;

/******************************* ENTRADAS DEL PROC *******************************/
static struct proc_dir_entry *root_proc_file;
static struct proc_dir_entry *activar_proc_file;
static struct proc_dir_entry *desactivar_proc_file;
static struct proc_dir_entry *monitor_proc_file;

/***************************** FUNCIONES_FILE_OPS *****************************/
int procfile_write_activar(struct file *file, const char *buffer, unsigned long count,void *data)
{	
	return 0;
}

int procfile_write_desactivar(struct file *file, const char *buffer, unsigned long count,void *data)
{	
	return 0;
}

int procfile_read_monitor(char *buffer,char **buffer_location,off_t offset, int buffer_length, int *eof, void *data)
{
	return 0;
}

/******************************* FILE_OPS *******************************/
static struct file_operations fops_activar = {
	.owner = THIS_MODULE,
	.write = procfile_write_activar, //TODO
};

static struct file_operations fops_desactivar = {
	.owner = THIS_MODULE,
	.write = proc_write_desactivar, //TODO
};

static struct file_operations fops_monitor = {
	.owner = THIS_MODULE,
	.read = proc_read_monitor, //TODO
};

/********************** INIT Y EXIT DEL MODULO ***************************/

/**
 *This function is called when the module is loaded
 *
 */
int init_module()
{

	/* creamos el /proc/dir */
	root_proc_file = proc_mkdir(PROC_ROOT_NAME, NULL);
	/* si no se ha creado bien, lo borramos */
	if (root_proc_file == NULL){
		remove_proc_entry(PROC_ROOT_NAME, NULL);
		printk(KERN_ALERT "Error: No se ha inicializado /proc/%s\n",PROC_ROOT_NAME);
		return -ENOMEM;
	}
	
	printk(KERN_ALERT "/proc/%s creado\n", PROC_ROOT_NAME);
	
	activar_proc_file = proc_create(PROC_ACT_NAME, 0644, root_proc_file, &fops_activar);
	if (activar_proc_file == NULL){
		remove_proc_entry(PROC_ACT_NAME, root_proc_file);
		printk(KERN_ALERT "Error: No se ha inicializado /proc/%s/%s\n",PROC_ROOT_NAME, PROC_ACT_NAME);
		return -ENOMEM;
	}
	
	//TODO desactivar_proc_file;
	//TODO monitor_proc_file;
	

	return 0;	/* everything is ok */
}

/**
 *This function is called when the module is unloaded
 *
 */
void cleanup_module()
{
	removeAll();
	remove_proc_entry(PROCFS_NAME, NULL);
	printk(KERN_ALERT "/proc/%s removed\n", PROCFS_NAME);
}
